import m, { ClassComponent, Vnode, VnodeDOM } from "mithril"
import { clone, lastIndex } from "@tutao/tutanota-utils"
import { formatShortTime, formatTime } from "../../misc/Formatter"
import { getIntervalAsMinutes, SUBROWS_PER_INTERVAL, TimeRange, TimeScale } from "./CalendarTimeGrid"
import { px } from "../../gui/size"
import { Time } from "../date/Time"
import { styles } from "../../gui/styles"
import { CalendarTimeCell, CalendarTimeCellAttrs, CellActionHandler } from "./CalendarTimeCell"
import { TimeBadge, TimeBadgeAttrs, TimeBadgeVarient } from "./TimeBadge"
import { TimeIndicator } from "./TimeIndicator"

export interface CalendarTimeColumnAttrs {
	intervals: Array<Time>
	layout: {
		width: number
		subColumnCount: number
		rowCount: number
		gridRowHeight: number
	}
	baseDate?: Date
	onCellPressed?: CellActionHandler
	/**
	 * When currentTime is defined we show the timeBadge
	 */
	currentTime?: Time
	amPm: boolean
}

const TIME_CELL_ID_PREFIX = "time-cell-"

export class CalendarTimeColumn implements ClassComponent<CalendarTimeColumnAttrs> {
	private columnHeight = 0

	oncreate(vnode: VnodeDOM<CalendarTimeColumnAttrs>) {
		this.columnHeight = vnode.dom.clientHeight
	}

	view({ attrs }: Vnode<CalendarTimeColumnAttrs>) {
		return m(
			".rel.grid.gap.border-right.gap-1",
			{
				style: {
					gridTemplateRows: `repeat(${attrs.layout.rowCount}, ${px(attrs.layout.gridRowHeight)})`,
					gridTemplateColumns: px(attrs.layout.width),
				},
			},
			[
				attrs.currentTime
					? m(
							".abs.abs-center-horizontally.z3.fit-content",
							{
								style: {
									top: px(TimeIndicator.calculateYPosition(attrs.currentTime, this.columnHeight)),
									transform: "translateY(-50%)",
								},
							},
							m(TimeBadge, {
								currentTime: attrs.currentTime,
								amPm: attrs.amPm,
								variant: TimeBadgeVarient.SMALL,
							} satisfies TimeBadgeAttrs),
						)
					: null,
				attrs.intervals.map((interval, intervalIndex) => {
					const parsedTime = interval.toDate()
					const formatedTime = styles.isDesktopLayout() ? formatTime(parsedTime) : formatShortTime(parsedTime)
					const rowStart = intervalIndex * SUBROWS_PER_INTERVAL + 1
					const rowEnd = rowStart + SUBROWS_PER_INTERVAL
					const showBorderBottom = intervalIndex !== lastIndex(attrs.intervals)

					return m(CalendarTimeCell, {
						dateTime: {
							baseDate: attrs.baseDate,
							time: interval,
						},
						layout: {
							rowBounds: {
								start: rowStart,
								end: rowEnd,
							},
							subColumnCount: attrs.layout.subColumnCount,
						},
						interactions: { onCellPressed: attrs.onCellPressed },
						text: formatedTime,
						showBorderBottom,
					} as CalendarTimeCellAttrs)
				}),
			],
		)
	}

	static getTimeCellId(hour: number): string {
		return `${TIME_CELL_ID_PREFIX}${hour}`
	}

	static createTimeColumnIntervals(timeScale: TimeScale, timeRange: TimeRange): Array<Time> {
		let timeInterval = getIntervalAsMinutes(timeScale)
		const numberOfIntervals = (timeRange.start.diff(timeRange.end) + timeInterval) / timeInterval
		const timeKeys: Array<Time> = []

		for (let i = 0; i < numberOfIntervals; i++) {
			const agendaRowTime = clone(timeRange.start).add({ minutes: timeInterval * i })
			timeKeys.push(agendaRowTime)
		}

		return timeKeys
	}
}
